// generating config files for a physical node
// Created: Apr. 14, 2023 by SUN Yazhou, asia.rabbit@163.com

#include <unistd.h>
#include <iostream>
#include "PN.h"

using std::endl;
using std::cerr;

PN::PN(const Node &n, CRATE_TYPE type) : fn(n), fType(type){
  fIP = fn["ip"].as<string>();
} // end ctor

PN::~PN(){
  for(auto &p : fLnMap) if(p.second) delete p.second;
} // end dtor

void PN::Generate(){
  ff.open(fIP.c_str());
  Head();
  for(auto &p : fLnMap) ff << *p.second << endl;
} // end member function Generate

// generate the head of the file
void PN::Head(){
  char tt[128]; time_t timeReal;
	time(&timeReal); timeReal = timeReal + 8*3600;
	tm* t = gmtime(&timeReal);
	sprintf(tt, "%d-%02d-%02d %02d:%02d:%02d\n", t->tm_year + 1900, t->tm_mon + 1,
    t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);

  ff << "##  Automatically generated by program `sketch` at " << tt;
	ff << "##--------------------- Version 1.1 Aug 11, 2023 ---------------------" << endl;
	ff << "##----------------- https://gitee.com/asiarabbit/skt -----------------" << endl;
	ff << "##_______________Author: SUN Yazhou, asia.rabbit@163.com______________" << endl;
  
  ff << endl << endl;
  ff << "[PNInfo]\nStreamNum=1\n\n[stream0]\nLnNum=" << fLnMap.size() << endl;
  ff << endl << endl;
} // end member function Head


LN *PN::AddLn(int id, LN *ln){
  if(fLnMap.count(id)){
    cerr << "error: ln with id =" << id << " has been added." << endl;
    exit(-1);
  } // end if
  fLnMap[id] = ln;
  return ln;
} // end member function AddLn


// generate config files for various ln types //
LN *PN::data_save(int id){
  return AddLn(id, new LN(id, DATA_SAVE, fType, DATA));
} // end of member function data_save

LN *PN::sys_console_gui(int id){
  return AddLn(id, new LN(id, SYS_CONSOLE_GUI, fType));
} // end of member function sys_console_gui

LN *PN::reduce_index(int id, STREAM_TYPE type){
  return AddLn(id, new LN(id, REDUCE_INDEX, fType, type, type == DATA ? "reduce" : "passby"));
} // end of member function reduce_index

LN *PN::map_index(int id, STREAM_TYPE type){
  return AddLn(id, new LN(id, MAP_INDEX, fType, type, type == DATA ? "alternate" : "broadcast"));
} // end of member function map_index

LN *PN::receive(int id, STREAM_TYPE type){
  LN *p = new LN(id, RECEIVE, fType, type);
  p->SetIP(fIP);
  return AddLn(id, p);
} // end of member function receive

LN *PN::transmit(int id, STREAM_TYPE type){
  LN *p = new LN(id, TRANSMIT, fType, type, type == DATA ? "buffer" : "nobuffer");
  p->SetIP(fIP);
  return AddLn(id, p);
} // end of member function transmit

LN *PN::dsi(int id, const string opt){
  return AddLn(id, new LN(id, DSI, fType, STREAM_OTHER, opt));
} // end of member function dsi

LN *PN::master_trigger(int id, const string opt){
  return AddLn(id, new LN(id, MASTER_TRIGGER, fType, STREAM_OTHER, opt));
} // end of member function dsi

LN *PN::slave_trigger(int id, const string opt){
  return AddLn(id, new LN(id, SLAVE_TRIGGER, fType, STREAM_OTHER, opt));
} // end of member function dsi
